﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.IO;

namespace AlyDdns
{
    public static class UIService
    {
        static AlyDnsService AlyDnsService=new AlyDnsService();
        public static async Task StartAlive(int port)
        {
            using (HttpListener listener = new HttpListener())
            {
                listener.Prefixes.Add($"http://+:{port}/");
                listener.Start();
                Console.WriteLine($"Alive Service Has Started! Port:{port}");
                while (true)
                {
                    var context = await listener.GetContextAsync();
                    _ = Task.Factory.StartNew((obj) => {
                        var theContext = obj as HttpListenerContext;
                        if (theContext?.Request.Url == null)
                        {
                            return;
                        }
                        theContext.Response.StatusCode = 200;
                        theContext.Response.ContentType = "text/html";                        
                        theContext.Response.OutputStream.Write(Encoding.UTF8.GetBytes("1"));
                        theContext.Response.OutputStream.Flush();
                        theContext.Response.Close();
                        Console.WriteLine($"{DateTime.Now}:Alive {theContext.Request.Url}");
                    }, context);
                }
            }
        }
        public static async Task Start(int port,string? cfg=null)
        {
            using (HttpListener listener = new HttpListener())
            {
                listener.Prefixes.Add($"http://+:{port}/");
                listener.Start();
                Console.WriteLine($"Service Has Started! Port:{port}");
                if (cfg != null)
                {
                    _=Task.Run(() => AlyDnsService.Start(cfg));
                }
                while (true)
                {
                    var context = await listener.GetContextAsync();
                    _ = Task.Factory.StartNew((obj) => {
                        var theContext = obj as HttpListenerContext;
                        if (theContext?.Request.Url == null)
                        {
                            return;
                        }
                        if (theContext.Request.Url.AbsolutePath.StartsWith("/cmd/"))
                        {
                            theContext.Response.StatusCode = 200;
                            ExecCmd(theContext);
                        }
                        else
                        {
                            theContext.Response.StatusCode = 200;
                            GetUI(theContext);
                        }
                    }, context);
                }
            }
        }
        static void GetUI(HttpListenerContext theContext)
        {
            if (theContext.Request.Url == null)
                return;
            var url = theContext.Request.Url.AbsolutePath;
            if (url.EndsWith("/"))
            {
                url = url.Insert(1, "UI/");
                url += "index.html";
            }
            url = url.Remove(0, 1);
            byte[] buffer = new byte[1024];
            if (!File.Exists(url))
            {
                theContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                theContext.Response.Close();
                return;
            }
            theContext.Response.ContentType = "text/html";
            using (var htmlFileStream = File.OpenRead(url))
            {
                while (htmlFileStream.Position < htmlFileStream.Length)
                {
                    long count = htmlFileStream.Length - htmlFileStream.Position;
                    if (count > buffer.Length)
                    {
                        count = buffer.Length;
                    }
                    htmlFileStream.Read(buffer, 0, (int)count);
                    theContext.Response.OutputStream.Write(buffer, 0, (int)count);
                }
                theContext.Response.OutputStream.Flush();
                theContext.Response.Close();
            }
        }
        static void ExecCmd(HttpListenerContext theContext)
        {
            if (theContext.Request.Url == null)
                return;
            var cmd = theContext.Request.Url.AbsolutePath.Remove(0, 5);
            switch (cmd)
            {
                case "GetAlyDdnsStatus":
                    GetAlyDdnsStatus(theContext);
                    break;
                case "StartAlyDdns":
                    StartAlyDdns(theContext);
                    break;
                case "StopAlyDdns":
                    StopAlyDdns(theContext);
                    break;
                case "GetAlyDdnsCfgList":
                    GetAlyDdnsCfgList(theContext);
                    break;
                default:
                    theContext.Response.Close();
                    break;
            }
        }
        static void GetAlyDdnsCfgList(HttpListenerContext theContext)
        {
            var list=Directory.GetFiles(".", "*.json");
            var outText = String.Join("|", list.Select(it => Path.GetFileNameWithoutExtension(it)).ToArray());
            theContext.Response.OutputStream.Write(Encoding.UTF8.GetBytes(outText));
            theContext.Response.OutputStream.Flush();
            theContext.Response.Close();
        }
        static void GetAlyDdnsStatus(HttpListenerContext theContext)
        {
            theContext.Response.OutputStream.Write(Encoding.UTF8.GetBytes(AlyDnsService.Status.ToString()));
            theContext.Response.OutputStream.Flush();
            theContext.Response.Close();
        }
        static void StartAlyDdns(HttpListenerContext theContext)
        {
            var cfg = theContext.Request.QueryString[0] + ".json";
            Task.Run(()=>AlyDnsService.Start(cfg));
            theContext.Response.OutputStream.Write(Encoding.UTF8.GetBytes(AlyDnsService.Status.ToString()));
            theContext.Response.OutputStream.Flush();
            theContext.Response.Close();
        }
        static void StopAlyDdns(HttpListenerContext theContext)
        {
            AlyDnsService.Stop();
            theContext.Response.OutputStream.Write(Encoding.UTF8.GetBytes(AlyDnsService.Status.ToString()));
            theContext.Response.OutputStream.Flush();
            theContext.Response.Close();
        }
    }
}
